Introduction

This is a notebook to begin to investigate the soil water content sensor data for the FFAR project

Data

Load all of the zentra information and extract the water content data into a dataframe wc_dat

Next, parse the “Site” column into Treatment, Block, and Triangle columns

head(wc_dat)
##     X timestamp_utc                  datetime tz_offset value error_flag
## 961 0    1660064400 2022-08-09 13:00:00-04:00    -14400 0.028      False
## 962 1    1660060800 2022-08-09 12:00:00-04:00    -14400 0.028      False
## 963 2    1660057200 2022-08-09 11:00:00-04:00    -14400 0.028      False
## 964 3    1660053600 2022-08-09 10:00:00-04:00    -14400 0.028      False
## 965 4    1660050000 2022-08-09 09:00:00-04:00    -14400 0.028      False
## 966 5    1660046400 2022-08-09 08:00:00-04:00    -14400 0.028      False
##     error_description Port Site LoggerName    OutputName         datetimeUTC
## 961                      3   MI   z6-18279 Water Content 2022-08-09 17:00:00
## 962                      3   MI   z6-18279 Water Content 2022-08-09 16:00:00
## 963                      3   MI   z6-18279 Water Content 2022-08-09 15:00:00
## 964                      3   MI   z6-18279 Water Content 2022-08-09 14:00:00
## 965                      3   MI   z6-18279 Water Content 2022-08-09 13:00:00
## 966                      3   MI   z6-18279 Water Content 2022-08-09 12:00:00
##           Name Treatment Block Triangle Bl_Tri
## 961 MI-PR_9_11        PR     9       11   9_11
## 962 MI-PR_9_11        PR     9       11   9_11
## 963 MI-PR_9_11        PR     9       11   9_11
## 964 MI-PR_9_11        PR     9       11   9_11
## 965 MI-PR_9_11        PR     9       11   9_11
## 966 MI-PR_9_11        PR     9       11   9_11

Then remove known bad stretches of data due to sensor failure

wc_dat <- subset(wc_dat, !(Name == "WY_AD-11-12" & Port == 2))
wc_dat <- wc_dat[!(wc_dat$Name == "MI-AD_9_1" & wc_dat$datetimeUTC < as_datetime("2022-8-15 19:00:00")), ]
wc_dat <- wc_dat[!(wc_dat$Name == "MI-PR_9_9" & wc_dat$Port == 3 &
                   wc_dat$datetimeUTC < as_datetime("2022-8-5 00:00:00") &
                   wc_dat$datetimeUTC > as_datetime("2022-7-28 00:00:00")), ]
wc_dat <- wc_dat[!(wc_dat$Name == "MI-PR_8_11" & wc_dat$Port == 3 &
                   wc_dat$datetimeUTC < as_datetime("2022-7-16 18:00:00") &
                   wc_dat$datetimeUTC > as_datetime("2022-7-16 12:00:00")), ]
wc_dat <- wc_dat[!(wc_dat$Name == "RR_PR_4_7" & wc_dat$Port == 3 &
                   wc_dat$datetimeUTC < as_datetime("2022-10-05 11:00:00") &
                   wc_dat$datetimeUTC > as_datetime("2022-8-24 02:00:00")), ]
wc_dat <- wc_dat[!(wc_dat$Name == "RR_PR_4_7" & wc_dat$Port == 3 &
                   wc_dat$datetimeUTC < as_datetime("2022-12-07 13:00:00") &
                   wc_dat$datetimeUTC > as_datetime("2022-11-04 12:00:00")), ]

Visualize all Water Content Data for each sensor individually

t1 <- as_datetime("2022-07-01 00:00:00")
t2 <- as_datetime("2023-4-6 00:00:00")

for (site in unique(wc_dat$Site)){
    for (block in unique(wc_dat$Block[wc_dat$Site == site])){
            tr <- "AD"
            dat <- subset(wc_dat, Site == site & Block == block & Treatment == tr)
            p1 <- get_wc_plot(dat, t1, t2, tr)
            tr <- "PR"
            dat <- subset(wc_dat, Site == site & Block == block & Treatment == tr)
            p2 <- get_wc_plot(dat, t1, t2, tr)
            p <- ggarrange(p1, p2, ncol = 2)
            print(p)
    }
}

Investigate spatiotemporal stability and persistence

Calculate the mean water content and the mean relative difference (relative to other sensors at that site and treatment) of each sensor

For hourly data:

# Calculate the mean and standard deviation of each sensor relative to other sensors in that site/treatment pair
wc_dat_mean <- wc_dat %>% dplyr::group_by(Name, Site, Treatment, Block, Triangle, Port) %>% 
               dplyr::summarize(avg_value = mean(value, na.rm = TRUE), sd_value = sd(value, na.rm = TRUE))

wc_dat_mrd <- wc_dat %>% dplyr::group_by(Site, Treatment, Port, datetimeUTC) %>% 
               dplyr::mutate(sp_avg_value = mean(value, na.rm = TRUE), sp_sd_value = sd(value, na.rm = TRUE))

wc_dat_mrd$rd <- (wc_dat_mrd$value - wc_dat_mrd$sp_avg_value)/wc_dat_mrd$sp_avg_value

wc_dat_mrd_mean <- wc_dat_mrd %>% dplyr::group_by(Name, Site, Treatment, Block, Bl_Tri, Triangle, Port) %>% 
               dplyr::summarize(avg_rd = mean(rd, na.rm = TRUE), sd_rd = sd(rd, na.rm = TRUE))

… and for daily data:

# Reduce to daily data by extracting measurements from the noon hour only and repeat calculation
wc_dat_daily <- subset(wc_dat, hour(datetimeUTC) == 12)
wc_dat_daily_mean <- wc_dat_daily %>% dplyr::group_by(Name, Site, Treatment, Block, Triangle, Port) %>% 
               dplyr::summarize(avg_value = mean(value, na.rm = TRUE), sd_value = sd(value, na.rm = TRUE))

wc_dat_daily_mrd <- wc_dat_daily %>% dplyr::group_by(Site, Treatment, Port, datetimeUTC) %>% 
               dplyr::mutate(sp_avg_value = mean(value, na.rm = TRUE), sp_sd_value = sd(value, na.rm = TRUE))

wc_dat_daily_mrd$rd <- (wc_dat_daily_mrd$value - wc_dat_daily_mrd$sp_avg_value)/wc_dat_daily_mrd$sp_avg_value

wc_dat_daily_mrd_mean <- wc_dat_daily_mrd %>% dplyr::group_by(Name, Site, Treatment, Block, Bl_Tri, Triangle, Port) %>% 
               dplyr::summarize(avg_rd = mean(rd, na.rm = TRUE), sd_rd = sd(rd, na.rm = TRUE))

Water Content through time

Grouped for each site/treatment pair with spatially averaged water content in black

Relative Difference of Water Content

From the spatial average for each site/treatment pair (0 Line in black)

Temporal mean & standard deviation of relative difference in water content of each sensor

Unranked, ordered by Block

Ranked